package com.sxpcwlkj.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sxpcwlkj.common.code.entity.SmsConfigEntity;
import com.sxpcwlkj.common.enums.ConfigKeyNum;
import com.sxpcwlkj.common.utils.*;
import com.sxpcwlkj.datasource.entity.page.PageQuery;
import com.sxpcwlkj.datasource.entity.page.TableDataInfo;
import com.sxpcwlkj.datasource.mapper.BaseMapperPlus;
import com.sxpcwlkj.framework.sercice.impl.BaseServiceImpl;
import com.sxpcwlkj.redis.RedisUtil;
import com.sxpcwlkj.system.entity.SysConfig;
import com.sxpcwlkj.system.entity.bo.SysConfigBo;
import com.sxpcwlkj.system.entity.vo.SysConfigVo;
import com.sxpcwlkj.system.mapper.SysConfigMapper;
import com.sxpcwlkj.system.service.SysConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 系统配置
 *
 * @author 西决 942879858@qq.com
 * @since 1.0.0 2024-06-10
 */
@Slf4j
@Service("sys_config")
@RequiredArgsConstructor
public class SysConfigServiceImpl extends BaseServiceImpl<SysConfig, SysConfigVo,SysConfigBo> implements SysConfigService {

   private final SysConfigMapper baseMapper;


    @Override
    public BaseMapperPlus<SysConfig, SysConfigVo> getBaseMapper() {
        return baseMapper;
    }


    @Override
    public Boolean insert(SysConfigBo bo) {
        int row;
        SysConfig obj = MapstructUtil.convert(bo, SysConfig.class);
        if(obj!=null&&obj.getValueType()!=null&& !obj.getValueType().isEmpty()){
            if(obj.getValueType().equals("Array")){
                List<String> list = bo.getConfigValues();
                String result= DataUtil.getListToString(list);
                obj.setConfigValue(result);
            }
        }
        row = this.getBaseMapper().insert(obj);
        return row > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Serializable id) {
        return this.getBaseMapper().deleteById(id) > 0;
    }

    @Override
    public Boolean updateById(SysConfigBo bo) {
        int row;
        SysConfig obj = MapstructUtil.convert(bo, SysConfig.class);
        if(obj!=null&&obj.getValueType()!=null&& !obj.getValueType().isEmpty()){
            if(obj.getValueType().equals("Array")){
                List<String> list = bo.getConfigValues();
                String result=DataUtil.getListToString(list);
                obj.setConfigValue(result);
            }
        }
        if(obj!=null&&obj.getConfigKey()!=null&& !obj.getConfigKey().isEmpty()){
            SysConfig sysConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey,obj.getConfigKey()).last("LIMIT 1"));
            if(sysConfig!=null){
                obj.setId(sysConfig.getId());
            }
        }
        row = this.getBaseMapper().updateById(obj);
        return row > 0;
    }

    @Override
    public SysConfigVo selectVoById(Serializable id) {
        SysConfigVo sysConfigVo = this.getBaseMapper().selectVoById(id);
        if(sysConfigVo!=null&& !sysConfigVo.getConfigValue().isEmpty()){
            List<String> list = Arrays.asList(sysConfigVo.getConfigValue().split(","));
            sysConfigVo.setConfigValues(list);
            if(!list.isEmpty()){
                sysConfigVo.setValueType("Array");
            }else {
                sysConfigVo.setValueType("String");
            }
        }
        return sysConfigVo;
    }


    @Override
    public TableDataInfo<SysConfigVo> selectListVoPage(SysConfigBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysConfig> lqw = buildQueryWrapper(bo);
        Page<SysConfigVo> page = baseMapper.selectVoPage(pageQuery.build(),lqw);
        return TableDataInfo.build(page);
    }


    private LambdaQueryWrapper<SysConfig> buildQueryWrapper(SysConfigBo query){
        if(query==null){
            query=new SysConfigBo();
        }
        //Map<String, Object> params = query.getParams();
        LambdaQueryWrapper<SysConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StringUtil.isNotEmpty(query.getConfigName()), SysConfig::getConfigName, query.getConfigName());
        wrapper.eq(StringUtil.isNotEmpty(query.getConfigKey()), SysConfig::getConfigKey, query.getConfigKey());
        wrapper.eq(StringUtil.isNotEmpty(query.getConfigType()), SysConfig::getConfigType, query.getConfigType());
        wrapper.eq(StringUtil.isNotEmpty(query.getStatus()), SysConfig::getStatus, query.getStatus());
        return wrapper;
    }

    private final ApplicationContext applicationContext;

    @Override
    public Boolean updateByCodes(List<SysConfigBo> bos) {
        if(bos!=null&& !bos.isEmpty()){
            for (SysConfigBo bo : bos) {
                if(bo.getConfigKey()==null|| bo.getConfigKey().isEmpty()){
                    continue;
                }
                this.updateById(bo);
                this.initBase();
                this.initSms();
                applicationContext.publishEvent(new ContextRefreshedEvent(applicationContext));
            }
            return true;
        }
        return false;
    }

    @Override
    public List<SysConfigBo> selectByCodes(List<SysConfigBo> bos) {

        for (SysConfigBo bo : bos) {
            SysConfigVo vo = baseMapper.selectVoOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, bo.getConfigKey()).last("LIMIT 1"));
            if(vo==null){
                if(bo.getConfigKey()==null|| bo.getConfigKey().isEmpty()){
                    continue;
                }
                bo.setStatus(0);
                bo.setConfigType(1);
                this.insert(bo);
            }else {
                bo.setConfigValue(vo.getConfigValue());
                if(bo.getValueType()!=null&& !bo.getValueType().isEmpty()){
                    List<String> list = Arrays.asList(vo.getConfigValue().split(","));
                    if(list!=null&& !list.isEmpty()){
                        bo.setValueType("Array");
                        //去除空字符串
                        list = list.stream().filter(str -> !str.equals("")).collect(Collectors.toList());
                        //去除空格
                        list = list.stream().map(s -> s.trim()).collect(Collectors.toList());
                        //去除重复
                        list = list.stream().distinct().collect(Collectors.toList());
                    }else{
                        bo.setValueType("String");
                    }
                    bo.setConfigValues(list);
                }
                bo.setConfigName(vo.getConfigName());
                bo.setConfigType(vo.getConfigType());
                bo.setStatus(vo.getStatus());
                bo.setId(vo.getId());
            }
        }
        return bos;
    }

    @Override
    public Boolean initSms() {
        List<SysConfig> sysSms = baseMapper.selectList(new LambdaQueryWrapper<SysConfig>().likeRight(SysConfig::getConfigKey, "sys_sms_"));
        //转为Map集合
        List<SmsConfigEntity> convert = BeanCopyUtil.convert(sysSms, SmsConfigEntity.class);
        RedisUtil.setCacheList(ConfigKeyNum.config_sms.getKey(),convert);
        RedisUtil.expire(ConfigKeyNum.config_sms.getKey(), Duration.ofDays(99999999));
        return true;
    }

    @Override
    public Boolean initBase() {
        List<SysConfig> sysSms = baseMapper.selectList(new LambdaQueryWrapper<SysConfig>().likeRight(SysConfig::getConfigKey, "sys_base_"));
        //转为Map集合
        List<SmsConfigEntity> convert = BeanCopyUtil.convert(sysSms, SmsConfigEntity.class);
        RedisUtil.setCacheList(ConfigKeyNum.config_base.getKey(),convert);
        RedisUtil.expire(ConfigKeyNum.config_base.getKey(), Duration.ofDays(99999999));
        return true;
    }
}
